package gapidt.analysis.detectors;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import edu.stanford.nlp.util.StringUtils;
import gapidt.analysis.APIDesignAnalysisUtils;
import gapidt.analysis.ASTUtils;
import gapidt.analysis.DesignProblem;
import gapidt.analysis.IDesignProblemsDetector;
import gapidt.analysis.designproblems.InappropriateMethodComments;
import gapidt.analysis.designproblems.LackingMethodComments;
import gapidt.nlp.SemanticAnalyzer;
import gapidt.nlp.SemanticUtils;
import gapidt.plugin.AnalysisResultsManager;

import org.apache.commons.lang.ArrayUtils;
import org.apache.log4j.Logger;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.JavaModelException;

public class InappropriateOrLackingCommentsDetector extends IDesignProblemsDetector<IMethod> {

	static Logger logger = Logger.getLogger(InappropriateOrLackingCommentsDetector.class);
	
	public static int minSimilarityDegree = 10;
	public static int maxCommentsWords = 10;
	
	public InappropriateOrLackingCommentsDetector(){
		super(IMethod.class);
	}
	
	public static int getMinSimilarityDegree() {
		return minSimilarityDegree;
	}

	public static void setMinSimilarityDegree(int minSimilarityDegree) {
		InappropriateOrLackingCommentsDetector.minSimilarityDegree = minSimilarityDegree;
	}

	@Override
	public List<DesignProblem<?>> detectProblems(IMethod method){
		
		List<DesignProblem<?>> designProblems = new ArrayList<DesignProblem<?>>();
		
		if(!APIDesignAnalysisUtils.isServiceMethod(method)){
			return designProblems;
		}
		
		String comments = ASTUtils.getMethodComments(method).trim();
		//Detect lacking comments
		if(comments.isEmpty()) {
			designProblems.add(new LackingMethodComments(method));
			AnalysisResultsManager.getInstance().addDesigProblemCount(getClass().getSimpleName());
		}
		
		//Detect inappropriate comments
		if(!comments.isEmpty()){
			
			String firstCommentsSentence = SemanticUtils.getFirstSentence(comments, maxCommentsWords);
			
			String methodNameHuman = SemanticUtils.camelCase2Human(method.getElementName().toString());
			
			try {
				//Concatenar nombres de parámetros al nombre del método para agregar información semántica
				Set<String> parameterWords = new HashSet<String>();
				
				for(String param : method.getParameterNames()){
					String[] words = SemanticUtils.camelCase2Human(param).split("\\s+");
					for(String word : words){
						if(!word.trim().isEmpty())
							parameterWords.add(word.trim().toLowerCase());
					}
				}
				
				if(parameterWords.size() > 0){
					methodNameHuman += ", with " + StringUtils.join(parameterWords, ", ");
				}
				
			} catch (JavaModelException e) {
				// No hacer nada
			}
			
			double similarity = SemanticAnalyzer.similarityDegree(methodNameHuman, firstCommentsSentence); 
			
			logger.debug("Similarity between '"+methodNameHuman+"' and '"+firstCommentsSentence+"': "+(similarity*100.0)+" (min. similarity "+minSimilarityDegree+")");
			
			if(similarity*100.0 < minSimilarityDegree){
				designProblems.add(new InappropriateMethodComments(method));
				AnalysisResultsManager.getInstance().addDesigProblemCount(getClass().getSimpleName());
			}
		}

		return designProblems;
	}
	
}
